﻿using System;
using System.Linq;
using System.Linq.Expressions;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;

namespace Infrastructure.Data.Uow
{
    public static class IQueryableExtensions
    {
        /// <summary>
        /// Include extension method for IDbSet
        /// <example>
        /// var query = ReturnTheQuery();
        /// query = query.Include(customer=>customer.Orders);//"Orders"
        /// //or
        /// query = query.Include(customer=>customer.Orders.Select(o=>o.OrderDetails) //"Orders.OrderDetails"
        /// </example>
        /// </summary>
        /// <typeparam name="TEntity">Type of elements in IQueryable</typeparam>
        /// <typeparam name="TEntity">Type of navigated element</typeparam>
        /// <param name="queryable">Queryable object</param>
        /// <param name="path">Expression with path to include</param>
        /// <returns>Queryable object with include path information</returns>
        public static IQueryable<TEntity> Include<TEntity, TProperty>(this IDbSet<TEntity> queryable, Expression<Func<TEntity, TProperty>> path)
            where TEntity : class
        {
            var objectQuery = queryable as DbQuery<TEntity>;
            if (objectQuery != null)
            {
                return objectQuery.Include(path);
            }
            else
            {
                return queryable;
            }
        }

        public static IQueryable<KEntity> OfType<TEntity, KEntity>(this IQueryable<TEntity> queryable)
            where TEntity : class
            where KEntity : class,TEntity
        {
            var objectQuery = queryable as DbQuery<TEntity>;
            if (objectQuery != null)
            {
                return objectQuery.OfType<KEntity>();
            }
            else
            {
                return queryable.OfType<KEntity>();
            }
        }
    }
}
